package com.world.rickcloudendpoint.common.utils;

import com.world.rickcloudendpoint.common.constant.GlobalConstants;
import lombok.extern.log4j.Log4j2;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @Description: 数字处理工具
 * @author: songjilei E-mail:
 * @Date: Created in 16:17 2019/9/29
 */
@Log4j2
public class NumberUtils {

    /**
     * 保留小数点3位有效小数
     *
     * @param divided 被除数
     * @param divisor 除数
     * @return 保留有效位数的小数，小数点后有效位数3位
     */
    public static String divide(Double divided, Double divisor) {
        return divide(String.valueOf(divided), String.valueOf(divisor));
    }

    /**
     * 保留小数点3位有效小数
     *
     * @param divided 被除数
     * @param divisor 除数
     * @return 保留有效位数的小数，小数点后有效位数3位
     */
    public static String divide(String divided, String divisor) {
        BigDecimal d1 = new BigDecimal(divided);
        BigDecimal d2 = new BigDecimal(divisor);

        if (d2.signum() == 0) {
            return "0";
        }

        BigDecimal divide = d1.divide(d2, 20, RoundingMode.HALF_UP);

        String tempValue = GlobalConstants.Constants.DECIMAL_FORMAT_TWENTY.format(divide.doubleValue());
        String[] valueArray = tempValue.split("\\.");

        String integerPart = valueArray[0];
        String decimalPart = valueArray[1];

        // 只有整数部分
        BigDecimal tempDecimal = new BigDecimal(decimalPart);
        if (tempDecimal.signum() == 0) {
            return integerPart;
        }

        char[] chars = decimalPart.toCharArray();
        int i = 0;
        for (char ch : chars) {
            if (ch != '0') {
                break;
            }
            i++;
        }

        // 获取4位有效数字
        int lengthValue = i + 4;
        String fourDigital = decimalPart.substring(0, lengthValue > 20 ? 20 : lengthValue);
        // 保留3位有效数字
        long threeDigitalValue = Math.round(Integer.parseInt(fourDigital) / 10.0);

        int singleDigit = (int) Math.floorMod(threeDigitalValue, 10);
        int tenDigit = (int) Math.floorMod(threeDigitalValue / 10, 10);
        int hundredsDigit = (int) Math.floorMod(threeDigitalValue / 100, 10);
        int thousandDigit = (int) Math.floorMod(threeDigitalValue / 1000, 10);

        String threeDigit;
        if (0 != thousandDigit) {
            threeDigit = fillZero(i - 1) + String.valueOf(thousandDigit);
        } else {
            if (0 == hundredsDigit) {
                if (0 == tenDigit) {
                    threeDigit = fillZero(i) + String.valueOf(singleDigit);
                } else {
                    if (0 == singleDigit) {
                        threeDigit = fillZero(i) + String.valueOf(tenDigit);
                    } else {
                        threeDigit = fillZero(i) + String.valueOf(tenDigit) + String.valueOf(singleDigit);
                    }
                }
            } else {
                if (0 == tenDigit) {
                    if (0 == singleDigit) {
                        threeDigit = fillZero(i) + String.valueOf(hundredsDigit);
                    } else {
                        threeDigit = fillZero(i) + String.valueOf(hundredsDigit) + "0" + String.valueOf(singleDigit);
                    }
                } else {
                    if (0 == singleDigit) {
                        threeDigit = fillZero(i) + String.valueOf(hundredsDigit) + String.valueOf(tenDigit);
                    } else {
                        threeDigit = fillZero(i) + String.valueOf(hundredsDigit) + String.valueOf(tenDigit) + String.valueOf(singleDigit);
                    }
                }
            }
        }

        if (i == 0) {
            // 小数部分进位整数部分
            if (new BigDecimal(thousandDigit).compareTo(BigDecimal.ZERO) > 0) {
                return new BigDecimal(integerPart).add(new BigDecimal(thousandDigit)).toString();
            } else {
                return new BigDecimal(integerPart).toString() + "." + threeDigit;
            }

        } else {
            return integerPart + "." + threeDigit;
        }

    }

    /**
     * 返回长度指定长度的“0”字符串
     *
     * @param length 字符串长度
     * @return 指定长度的“0”字符串
     */
    private static String fillZero(int length) {
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= length; i++) {
            sb.append('0');
        }
        return sb.toString();
    }


    /**
     * 专门对应小数点数字字符串是否为0 , 0.00000
     * 当字符串为null或空时就当作是0
     * 重点: 这里只针对确定 话单量 或 流量占比 是否为0的判断, 其他不适用
     *
     * @param digital 数字字符串
     * @return false: 不是0字符串; true: 是0的字符串
     */
    public static boolean dataStrCompareToZero(String digital) {
        if (digital == null || digital.trim().equals("")) {
            return true;
        }

        // 如果不是数字直接返回false
        if (!isNumeric(digital)) {
            return false;
        }

        String data = digital;
        // 小数
        if (digital.contains(".")) {
            data = digital.replaceAll("\\.", "");
        }

        String numChar = "123456789";
        for (int i = 0; i < data.length(); i++) {
            if (numChar.contains(String.valueOf(data.charAt(i)))) {
                return false;
            }
        }

        return true;

    }


    /**
     * 判断字符串是否是数字
     *
     * @param str 字符串
     * @return
     */
    public static boolean isNumeric(String str) {
        String bigStr;
        try {
            bigStr = new BigDecimal(str).toString();
        } catch (Exception e) {
            log.info(String.format("Str[%s] container Non-numeric char, the error is %s ", str, e.getMessage()));
            //异常 说明包含非数字。
            return false;
        }
        return true;
    }

    /**
     *
     * 双精度浮点型小数点向右移动N位，转换成长整型
     *
     * @param f
     * @param digit
     * @return
     */
    public static long doubleToLong(double f, int digit) {
        digit = Math.abs(digit);
        if (digit == 0) {
            return new BigDecimal(f).longValue();
        }
        int multiple = 1;
        for (int i = 0; i < digit; i++) {
            multiple *= 1e1;
        }
        return new BigDecimal(f * multiple).longValue();
    }

    /**
     * 长整型小数点向左移动N位，转换成小数
     * @param l
     * @param digit
     * @return
     */
    public static double longToDouble(long l, int digit) {
        digit = Math.abs(digit);
        if (digit == 0) {
            return l * 1.0;
        }
        int multiple = 1;
        for (int i = 0; i < digit; i++) {
            multiple *= 1e-1;
        }
        return new BigDecimal(l * multiple).setScale(digit).doubleValue();
    }

}
